﻿using System;
using System.Collections.Generic;
using System.Linq;
using Assist;
using Autodesk.Revit.DB;
using YArchitech.Revit;

namespace YJKRoom.RoomTagModule
{
	public class CentroidByView
	{
		public static bool GetViewCentroidPoint(ref XYZ ptC, CurveArray arCurves)
		{
			XYZ xyz = null;
			XYZ xyz2 = null;
			foreach (object obj in arCurves)
			{
				Curve curve = (Curve)obj;
				Line line = curve as Line;
				if (!(line == null))
				{
					xyz = line.Direction;
					break;
				}
			}
			foreach (object obj2 in arCurves)
			{
				Curve curve2 = (Curve)obj2;
				Line line2 = curve2 as Line;
				if (!(line2 == null))
				{
					XYZ direction = line2.Direction;
					if (!GeoUtil.IsParallel(direction, xyz))
					{
						xyz2 = line2.Direction;
						break;
					}
				}
			}
			if (xyz == null || xyz2 == null)
			{
				return false;
			}
			CurveArray curveArray = new CurveArray();
			CurveArray curveArray2 = new CurveArray();
			foreach (object obj3 in arCurves)
			{
				Curve curve3 = (Curve)obj3;
				Line line3 = curve3 as Line;
				if (!(line3 == null))
				{
					XYZ direction2 = line3.Direction;
					if (GeoUtil.IsParallel(direction2, xyz))
					{
						curveArray.Append(curve3);
					}
					else if (GeoUtil.IsParallel(direction2, xyz2))
					{
						curveArray2.Append(curve3);
					}
				}
			}
			if (curveArray.Size + curveArray2.Size != arCurves.Size)
			{
				return false;
			}
			Curve curve4 = null;
			double maxLength = CentroidByView.GetMaxLength(ref curve4, curveArray);
			Curve curve5 = null;
			double maxLength2 = CentroidByView.GetMaxLength(ref curve5, curveArray2);
			List<Curve> list = new List<Curve>();
			foreach (object obj4 in curveArray)
			{
				Curve item = (Curve)obj4;
				list.Add(item);
			}
			List<Curve> list2 = new List<Curve>();
			foreach (object obj5 in curveArray2)
			{
				Curve item2 = (Curve)obj5;
				list2.Add(item2);
			}
			for (int i = 0; i < list.Count - 1; i++)
			{
				Line curve6 = list[i] as Line;
				Line curveBase = Line.CreateUnbound(curve6.GetEndPoint(0), curve6.GetEndPoint(1) - curve6.GetEndPoint(0));
				for (int j = i + 1; j < list.Count; j++)
				{
					Line curve7 = list[j] as Line;
					if (CentroidByView.IsPointOnCurve(curveBase, curve7.GetEndPoint(0)))
					{
						list.RemoveAt(j);
						j--;
					}
				}
			}
			for (int k = 0; k < list2.Count - 1; k++)
			{
				Line curve8 = list2[k] as Line;
				Line curveBase2 = Line.CreateUnbound(curve8.GetEndPoint(0), curve8.GetEndPoint(1) - curve8.GetEndPoint(0));
				for (int l = k + 1; l < list2.Count; l++)
				{
					Line curve9 = list2[l] as Line;
					if (CentroidByView.IsPointOnCurve(curveBase2, curve9.GetEndPoint(0)))
					{
						list2.RemoveAt(l);
						l--;
					}
				}
			}
			if (list.Count > 4 || list2.Count > 4)
			{
				return false;
			}
			if (list.Count == 2 || list2.Count == 2)
			{
				return false;
			}
			if (list.Count == 4 || list2.Count == 4)
			{
				return false;
			}
			Curve curve10 = curve4;
			if (maxLength < maxLength2)
			{
				curve10 = curve5;
			}
			XYZ hyendPoint = curve10.GetEndPoint(0);
			XYZ hyendPoint2 = curve10.GetEndPoint(1);
			XYZ xyz3 = curve10.Evaluate(0.5, true);
			Line line4 = Line.CreateUnbound(hyendPoint, hyendPoint2 - hyendPoint);
			foreach (object obj6 in arCurves)
			{
				Curve curve11 = (Curve)obj6;
				Line line5 = curve11 as Line;
				XYZ hyendPoint3 = line5.GetEndPoint(0);
				XYZ hyendPoint4 = line5.GetEndPoint(1);
				XYZ xyz4 = line5.Evaluate(0.5, true);
				if (GeoUtil.IsPointEqual(hyendPoint3, hyendPoint) || GeoUtil.IsPointEqual(hyendPoint3, hyendPoint2) || GeoUtil.IsPointEqual(hyendPoint4, hyendPoint) || GeoUtil.IsPointEqual(hyendPoint4, hyendPoint2))
				{
					XYZ xyzpoint = line4.Project(xyz4).XYZPoint;
					XYZ xyz5 = xyz4 - xyzpoint;
					ptC = xyz3 + xyz5;
					if (CentroidByView.IsPointInCurves(ptC, arCurves) == 1)
					{
						return true;
					}
				}
			}
			return false;
		}

		public static bool GetAdjustCentroidPoint(ref XYZ ptC, CurveArray arCurves, Document doc)
		{
			XYZ xyz = XYZ.BasisX;
			if (arCurves.Size > 0)
			{
                YJKCurve hycurve = new YJKCurve(arCurves.get_Item(0));
				double z = hycurve.EndPoint.Z;
				ptC = new XYZ(ptC.X, ptC.Y, z);
			}
			List<List<XYZ>> list = new List<List<XYZ>>();
			double num = 0.52359877559829882;
			int num2 = 0;
			for (;;)
			{
				double num3 = num * (double)num2;
				if (num3 >= Math.PI)
				{
					break;
				}
				xyz = new XYZ(Math.Cos(num3), Math.Sin(num3), 0.0);
				Line curve = Line.CreateUnbound(ptC, xyz);
				YJKCurve hycurve2 = new YJKCurve(curve);
				List<XYZ> list2 = new List<XYZ>();
				foreach (object obj in arCurves)
				{
					Curve otherCurve = (Curve)obj;
					List<XYZ> list3 = hycurve2.IntersectionAllPoint(otherCurve);
					if (list3 != null && list3.Count != 0)
					{
						list2.AddRange(list3);
					}
				}
				if (list2.Count > 0)
				{
					list.Add(list2);
				}
				num2++;
			}
			double num4 = -1.0;
			XYZ xyz2 = ptC;
			foreach (List<XYZ> list4 in list)
			{
				if (list4.Count == 2)
				{
					double num5 = list4[0].DistanceTo(list4[1]);
					if (num4 < 0.0)
					{
						xyz2 = list4[0] + (list4[1] - list4[0]) / 2.0;
						if (1 == CentroidByView.IsPointInCurves(xyz2, arCurves))
						{
							num4 = num5;
							ptC = xyz2;
						}
					}
					else if (num4 > num5)
					{
						xyz2 = list4[0] + (list4[1] - list4[0]) / 2.0;
						if (1 == CentroidByView.IsPointInCurves(xyz2, arCurves))
						{
							num4 = num5;
							ptC = xyz2;
						}
					}
				}
			}
			return true;
		}

		private static double GetMaxLength(ref Curve curveMaxLength, CurveArray arCurves)
		{
			double num = 0.0;
			foreach (object obj in arCurves)
			{
				Curve curve = (Curve)obj;
				Line line = curve as Line;
				if (!(line == null))
				{
					double length = line.Length;
					if (length > num)
					{
						num = length;
						curveMaxLength = curve;
					}
				}
			}
			return num;
		}

		public static int IsPointInCurves(XYZ ptIn, CurveArray arCurves)
		{
			if (arCurves.Size > 0)
			{
                YJKCurve hycurve = new YJKCurve(arCurves.get_Item(0));
				double z = hycurve.EndPoint.Z;
				ptIn = new XYZ(ptIn.X, ptIn.Y, z);
			}
			XYZ xyz = new XYZ(1.0, 0.0, 0.0);
			Line curve = Line.CreateUnbound(ptIn, xyz);
			YJKCurve hycurve2 = new YJKCurve(curve);
			List<XYZ> list = new List<XYZ>();
			foreach (object obj in arCurves)
			{
				Curve curve2 = (Curve)obj;
				new YJKCurve(curve2);
				if (CentroidByView.IsPointOnCurve(curve2, ptIn))
				{
					return 0;
				}
				Line line = curve2 as Line;
				if (!(line != null) || !GeoUtil.IsParallel(line.Direction, xyz))
				{
					List<XYZ> list2 = hycurve2.IntersectionAllPoint(curve2);
					if (list2 != null && list2.Count != 0)
					{
						for (int i = 0; i < list2.Count; i++)
						{
							XYZ ptIn2 = list2[i];
							if (CentroidByView.IsPointOnCurve2End(curve2, ptIn2) && !CentroidByView.IsPointOnCurveUp(curve2, ptIn2))
							{
								list2.RemoveAt(i);
								i--;
							}
						}
						list.AddRange(list2);
					}
				}
			}
			if (list.Count == 0)
			{
				return -1;
			}
			List<XYZ> list3 = new List<XYZ>();
			foreach (XYZ xyz2 in list)
			{
				XYZ pt = (xyz2 - ptIn).Normalize();
				if (GeoUtil.IsPointEqual(xyz, pt))
				{
					list3.Add(xyz2);
				}
			}
			if (list3.Count<XYZ>() % 2 != 1)
			{
				return -1;
			}
			return 1;
		}

		public static bool IsPointOnCurveUp(Curve curveBase, XYZ ptIn)
		{
			XYZ hyendPoint = curveBase.GetEndPoint(0);
			XYZ hyendPoint2 = curveBase.GetEndPoint(1);
			YJKCurve hycurve = new YJKCurve(curveBase.Clone());
			if (GeoUtil.IsPointEqual(hyendPoint, ptIn))
			{
				XYZ project = hycurve.GetProject(hyendPoint2, true);
				XYZ xyz = (hyendPoint2 - project).Normalize();
				return xyz.Y > 0.0;
			}
			if (GeoUtil.IsPointEqual(hyendPoint2, ptIn))
			{
				XYZ project2 = hycurve.GetProject(hyendPoint, true);
				XYZ xyz2 = (hyendPoint - project2).Normalize();
				return xyz2.Y > 0.0;
			}
			return false;
		}

		public static bool IsPointOnCurve2End(Curve curveBase, XYZ ptIn)
		{
			XYZ hyendPoint = curveBase.GetEndPoint(0);
			XYZ hyendPoint2 = curveBase.GetEndPoint(1);
			new YJKCurve(curveBase.Clone());
			return GeoUtil.IsPointEqual(hyendPoint, ptIn) || GeoUtil.IsPointEqual(hyendPoint2, ptIn);
		}

		public static bool IsPointOnCurve(Curve curveBase, XYZ ptIn)
		{
			try
			{
				IntersectionResult intersectionResult = curveBase.Project(ptIn);
                if (intersectionResult != null)
				{
					return GeoUtil.IsPointEqual(intersectionResult.XYZPoint, ptIn);
				}
			}
			catch
			{
				return false;
			}
			return false;
		}
	}
}
